#include <string.h>
#include <log4c.h>
#include "service.h"
#include "z_memory.h"
#include "z_logger.h"
#include "aliot.h"
#include "aiot_logpost_api.h"

#define SERVICE_NAME "logpost"

static int _logpost_log4c_open(log4c_appender_t *appender) {
}

static int _logpost_log4c_close(log4c_appender_t *appender) {
}

static int _logpost_log4c_append(log4c_appender_t *appender, const log4c_logging_event_t *event) {
    aiot_logpost_msg_t msg;
    bzero(&msg, sizeof(aiot_logpost_msg_t));

    switch (event->evt_priority) {
        case LOG4C_PRIORITY_FATAL:
        case LOG4C_PRIORITY_ALERT:
            msg.loglevel = AIOT_LOGPOST_LEVEL_FATAL;
            break;
        case LOG4C_PRIORITY_CRIT:
        case LOG4C_PRIORITY_ERROR:
            msg.loglevel = AIOT_LOGPOST_LEVEL_ERR;
            break;
        case LOG4C_PRIORITY_WARN:
        case LOG4C_PRIORITY_NOTICE:
            msg.loglevel = AIOT_LOGPOST_LEVEL_WARN;
            break;
        case LOG4C_PRIORITY_INFO:
            msg.loglevel = AIOT_LOGPOST_LEVEL_INFO;
            break;
        default:
            return 0;
    }

    msg.timestamp = event->evt_timestamp.tv_sec * 1000 + event->evt_timestamp.tv_usec / 1000;
    msg.code = event->evt_loc->loc_line;
    msg.module_name = event->evt_category;
    msg.content = event->evt_msg;

    void *handle = log4c_appender_get_udata(appender);
    return aiot_logpost_send(handle, &msg);
}

static log4c_appender_type_t _appender_type_logpost = {
        .name = SERVICE_NAME,
        .open = _logpost_log4c_open,
        .close = _logpost_log4c_close,
        .append = _logpost_log4c_append,
};

static void _logpost_event_handler_t(void *handle, const aiot_logpost_event_t *event, void *userdata) {
    switch (event->type) {
        case AIOT_LOGPOSTEVT_CONFIG_DATA:
            log_debug("config data ", event->data.config_data.on_off ? "on" : "off");
            break;
        default:
            break;
    }
}

void *_logpost_service_init(aliot_service_args_t *args) {
    void *logpost_handle = aiot_logpost_init();

    aiot_logpost_setopt(logpost_handle, AIOT_LOGPOSTOPT_MQTT_HANDLE, args->mqtt_handle);
    aiot_logpost_setopt(logpost_handle, AIOT_LOGPOSTOPT_EVENT_HANDLER, _logpost_event_handler_t);
    static uint8_t _sys_log_switch = 0;
    aiot_logpost_setopt(logpost_handle, AIOT_LOGPOSTOPT_SYS_LOG, &_sys_log_switch);

    return logpost_handle;
}

static void _logpost_service_fini(void **handle) {
    aiot_logpost_deinit(handle);
}

static void *_logpost_service_start(void *handle) {
    log4c_appender_t *appender = log4c_appender_get(SERVICE_NAME);
    log4c_appender_set_type(appender, &_appender_type_logpost);
    log4c_appender_set_udata(appender, handle);

    return NULL;
}

static int32_t _logpost_service_stop(void *handle) {
    log4c_appender_t *appender = log4c_appender_get(SERVICE_NAME);
    log4c_appender_delete(appender);
}

static aliot_service_t _logpost_service = {
        .name = SERVICE_NAME,
        .init = _logpost_service_init,
        .fini = _logpost_service_fini,
        .start = _logpost_service_start,
        .stop = _logpost_service_stop,
};

aliot_service_t *logpost_service_get() {
    return &_logpost_service;
}